package ws

import (
	"encoding/json"
	"fmt"
	"sync"

	"github.com/olahol/melody"
)

type Message struct {
	Type    string `json:"type"`           // "room" 或 "private"
	From    string `json:"from,omitempty"` // 发送者 ID，由服务端填充
	To      string `json:"to,omitempty"`   // 接收者 ID（私聊必填）
	Room    string `json:"room,omitempty"` // 群聊房间（服务端填充）
	Content string `json:"content"`        // 消息正文
}

var (
	UserSessions = make(map[string]*melody.Session) // userID -> session
	lock         sync.RWMutex
)

// 处理新连接
func HandleConnect(s *melody.Session) {
	userID := s.Request.URL.Query().Get("user")
	room := s.Request.URL.Query().Get("room")

	if userID == "" {
		_ = s.Close()
		return
	}

	lock.Lock()
	UserSessions[userID] = s
	lock.Unlock()

	s.Set("userID", userID)
	if room != "" {
		s.Set("room", room)
		_ = s.Write([]byte(userID + " to room " + room))
	} else {
		_ = s.Write([]byte(userID + " 连接成功"))
	}
}

// 处理消息
func HandleMessage(s *melody.Session, msg []byte, m *melody.Melody) {
	var mObj Message
	if err := json.Unmarshal(msg, &mObj); err != nil {
		_ = s.Write([]byte("消息解析错误"))
		return
	}

	// 自动填充发送者
	if v, ok := s.Get("userID"); ok {
		if userID, ok2 := v.(string); ok2 {
			mObj.From = userID
		}
	}

	switch mObj.Type {
	case "private":
		if mObj.To == "" {
			_ = s.Write([]byte("私发用户id不存在"))
			return
		}
		lock.RLock()
		target, ok := UserSessions[mObj.To]
		lock.RUnlock()

		if ok {
			out, _ := json.Marshal(mObj)
			_ = target.Write(out)
		} else {
			_ = s.Write([]byte("给用户发送消息失败"))
		}

	case "room":
		room := ""
		if v, ok := s.Get("room"); ok {
			if r, ok2 := v.(string); ok2 {
				room = r
			}
		}
		if room == "" {
			_ = s.Write([]byte("群id不存在"))
			return
		}

		mObj.Room = room
		out, _ := json.Marshal(mObj)

		_ = m.BroadcastFilter(out, func(ss *melody.Session) bool {
			if v, ok := ss.Get("room"); ok {
				if r, ok2 := v.(string); ok2 && r == room {
					senderID, _ := s.Get("userID")
					userID, _ := ss.Get("userID")
					return senderID != userID // 排除自己
				}
			}
			return false
		})

	default:
		_ = s.Write([]byte("默认错误"))
	}
}

// 断开连接
func HandleDisconnect(s *melody.Session) {
	if v, ok := s.Get("userID"); ok {
		if userID, ok2 := v.(string); ok2 {
			lock.Lock()
			delete(UserSessions, userID)
			lock.Unlock()
		}
	}
}

// 给指定用户发送消息（后台或服务端主动调用）
func SendToUser(userID string, content string) error {
	lock.RLock()
	session, ok := UserSessions[userID]
	lock.RUnlock()

	if !ok {
		return fmt.Errorf("user %s not online", userID)
	}

	msg := Message{
		From:    "system", // 或者后台管理者ID
		Content: content,
		Type:    "private",
		To:      userID,
	}

	out, _ := json.Marshal(msg)
	_ = session.Write(out)
	return nil
}

// 给指定房间发送消息（后台调用）
func SendToRoom(m *melody.Melody, room string, content string) {
	msg := Message{
		From:    "system",
		Type:    "room",
		Room:    room,
		Content: content,
	}

	out, _ := json.Marshal(msg)

	// 群发给房间内所有在线用户
	_ = m.BroadcastFilter(out, func(ss *melody.Session) bool {
		if v, ok := ss.Get("room"); ok {
			if r, ok2 := v.(string); ok2 && r == room {
				return true
			}
		}
		return false
	})
}
